<template>
    <a-dropdown :popPlacement="props.popPlacement" :useTargetWidth="false" class="a-input-date" v-model:popShown="state.popShown" :trigger="'none'">
        <a-control-group class="a-input-date">
            <a-input-string class="c-w-100" :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :disabled="formItemHook.myDisabled" :value="displayText" :placeholder="props.placeholder" :readonly="true" :clearable="props.clearable" :isInner="true" @click="state.popShown = !state.popShown" @clear="methods.input(undefined)"></a-input-string>
            <a-button v-if="props.attachButtonShown" class="c-f-shrink-0" :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :disabled="formItemHook.myDisabled" :square="true" ref="btn" @click="state.popShown = !state.popShown"><span class="fa fa-fw fa-calendar"></span></a-button></a-control-group>

        <template v-slot:pop>
            <div class="pop" :class="[
                !formItemHook.mySharp ? `c-round-${formItemHook.mySize}` : '',
                `c-p-${formItemHook.mySize}`,
                `c-shadow-${formItemHook.mySize}`,
            ]" :style="{ width: popWidth + 'px' }">
                <div v-if="state.isShowYear" class="c-f-v c-w-100">
                    <div class="c-f-h c-f-between-center">
                        <div class="c-f-h c-f-s-center" :class="[
                            `c-height-${formItemHook.mySize}`,
                            `c-font-size-${formItemHook.mySize}`,
                            `c-p-h-${formItemHook.mySize}`,
                            `c-front-color-${formItemHook.myColor}-reverse`,
                        ]">
                            <span>{{ state.currentYearTimespan.min }} -
                                {{ state.currentYearTimespan.max }}</span>
                        </div>
                        <a-control-group direction="v">
                            <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :square="true" :plain="true" :title="$t('AInputDate.LastPeriod')" :halfHeight="true" @click="
                                state.currentYearTimespan.min -= 20
                            state.currentYearTimespan.max -= 20;
                            ">
                                <span class="fa fa-fw fa-caret-up"></span>
                            </a-button>
                            <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :disabled="formItemHook.myDisabled" :square="true" :plain="true" :title="$t('AInputDate.NextPeriod')" :halfHeight="true" @click="
                                state.currentYearTimespan.min += 20
                            state.currentYearTimespan.max += 20;
                            ">
                                <span class="fa fa-fw fa-caret-down"></span>
                            </a-button>
                        </a-control-group>
                    </div>
                    <div class="c-f-h c-f-wrap">
                        <a-button v-for="a in methods.getArrayFromNumberSpan(
                            state.currentYearTimespan.min,
                            state.currentYearTimespan.max
                        )" :key="a" style="width: 20%" :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :plain="true" @click="methods.yearClick(a)">
                            {{ a }}
                        </a-button>
                    </div>
                </div>
                <div v-else-if="state.isShowMonth" class="c-f-v c-w-100">
                    <div class="c-f-h c-f-between-center">
                        <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :plain="true" :title="$t('AInputDate.SelectYear')" @click="
                            state.isShowYear = true
                        state.isShowMonth = false;
                        ">
                            <span>{{ tempResultInDayjs.format("YYYY") }}</span>
                            <span>-<span class="animate-flash">__</span>-__&#160;&#160;__:__:__</span>
                        </a-button>
                        <a-control-group direction="v">
                            <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :square="true" :plain="true" :title="$t('AInputDate.LastYear')" :halfHeight="true" @click="
                                state.tempValue = tempResultInDayjs
                                    .add(-1, 'year')
                                    .toDate()
                                ">
                                <span class="fa fa-fw fa-caret-up"></span>
                            </a-button>
                            <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :square="true" :plain="true" :title="$t('AInputDate.NextYear')" :halfHeight="true" @click="
                                state.tempValue = tempResultInDayjs
                                    .add(1, 'year')
                                    .toDate()
                                ">
                                <span class="fa fa-fw fa-caret-down"></span>
                            </a-button>
                        </a-control-group>
                    </div>
                    <div class="c-f-h c-f-wrap">
                        <a-button v-for="a in 12" :key="a" style="width: 25%" :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :plain="true" @click="methods.monthClick(a)">
                            {{ a }}
                        </a-button>
                    </div>
                </div>
                <div v-else-if="state.isShowDate" class="c-f-v c-w-100">
                    <div class="c-f-h c-f-between-center">
                        <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :plain="true" :title="$t('AInputDate.SelectMonth')" @click="
                            state.isShowMonth = true
                        state.isShowDate = false;
                        ">
                            <span>{{
                                tempResultInDayjs.format("YYYY-MM")
                            }}</span>
                            <span>-<span class="animate-flash">__</span>&#160;&#160;__:__:__</span>
                        </a-button>
                        <a-control-group direction="v">
                            <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :square="true" :plain="true" :title="$t('AInputDate.LastMonth')" :halfHeight="true" @click="
                                state.tempValue = tempResultInDayjs
                                    .add(-1, 'month')
                                    .toDate()
                                ">
                                <span class="fa fa-fw fa-caret-up"></span>
                            </a-button>
                            <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :square="true" :plain="true" :title="$t('AInputDate.NextMonth')" :halfHeight="true" @click="
                                state.tempValue = tempResultInDayjs
                                    .add(1, 'month')
                                    .toDate()
                                ">
                                <span class="fa fa-fw fa-caret-down"></span>
                            </a-button>
                        </a-control-group>
                    </div>
                    <div class="c-f-h">
                        <div v-for="a in [
                            $t('AInputDate.Monday'),
                            $t('AInputDate.Tuesday'),
                            $t('AInputDate.Wednesday'),
                            $t('AInputDate.Thursday'),
                            $t('AInputDate.Friday'),
                            $t('AInputDate.Saturday'),
                            $t('AInputDate.Sunday'),
                        ]" :key="a" style="width: 14.2857%" class="c-f-h c-f-center-center" :class="[
    `c-font-size-${formItemHook.mySize}`,
    `c-height-${formItemHook.mySize}`,
    `c-front-color-${formItemHook.myColor}-reverse`,
]">
                            {{ a }}
                        </div>
                    </div>
                    <div class="c-f-h c-f-wrap">
                        <div v-for="a in methods.getDayIndexOfFirstDate(
                            tempResult.Y,
                            tempResult.M
                        )" :key="a" style="width: 14.2857%"></div>
                        <a-button v-for="a in methods.getArrayFromNumberSpan(
                            1,
                            methods.getDaysCountOfMonth(tempResult.Y, tempResult.M)
                        )" :key="a + 100" style="width: 14.2857%" :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :plain="true" @click="methods.dateClick(a)">
                            {{ a }}
                        </a-button>
                    </div>
                </div>
                <div v-else-if="state.isShowHour" class="c-f-v c-w-100">
                    <div class="c-f-h c-f-between-center">
                        <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :plain="true" :title="$t('AInputDate.SelectDay')" @click="
                            state.isShowDate = true
                        state.isShowHour = false;
                        "><span>{{
    tempResultInDayjs.format("YYYY-MM-DD")
}}</span>
                            <span>&#160;&#160;<span class="animate-flash">__</span>:__:__</span>
                        </a-button>
                        <a-control-group direction="v">
                            <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :square="true" :plain="true" :title="$t('AInputDate.LastDay')" :halfHeight="true" @click="
                                state.tempValue = tempResultInDayjs
                                    .add(-1, 'day')
                                    .toDate()
                                ">
                                <span class="fa fa-caret-up"></span>
                            </a-button>
                            <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :square="true" :plain="true" :title="$t('AInputDate.NextDay')" :halfHeight="true" @click="
                                state.tempValue = tempResultInDayjs
                                    .add(1, 'day')
                                    .toDate()
                                ">
                                <span class="fa fa-caret-down"></span>
                            </a-button>
                        </a-control-group>
                    </div>
                    <div class="c-f-h c-f-wrap">
                        <a-button v-for="a in 24" :key="a" style="width: 16.6666%" :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :plain="true" @click="methods.hourClick(a - 1)">
                            {{ methods.paddingLeft(a - 1, 2) }}
                        </a-button>
                    </div>
                </div>
                <div v-else-if="state.isShowMinute" class="c-f-v c-w-100">
                    <div class="c-f-h c-f-between-center">
                        <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :plain="true" :title="$t('AInputDate.SelectHour')" @click="
                            state.isShowHour = true
                        state.isShowMinute = false;
                        "><span>{{
    tempResultInDayjs.format("YYYY-MM-DD HH")
}}</span>
                            <span>:<span class="animate-flash">__</span>:__</span>
                        </a-button>
                        <a-control-group direction="v">
                            <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :square="true" :plain="true" :title="$t('AInputDate.LastHour')" :halfHeight="true" @click="
                                state.tempValue = tempResultInDayjs
                                    .add(-1, 'hour')
                                    .toDate()
                                ">
                                <span class="fa fa-caret-up"></span>
                            </a-button>
                            <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :square="true" :plain="true" :title="$t('AInputDate.NextHour')" :halfHeight="true" @click="
                                state.tempValue = tempResultInDayjs
                                    .add(1, 'hour')
                                    .toDate()
                                ">
                                <span class="fa fa-caret-down"></span>
                            </a-button>
                        </a-control-group>
                    </div>
                    <div class="c-f-h c-f-wrap">
                        <a-button v-for="a in 60" :key="a" style="width: 10%" :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :plain="true" class="c-p-0" @click="methods.minuteClick(a - 1)">
                            {{ methods.paddingLeft(a - 1, 2) }}
                        </a-button>
                    </div>
                </div>
                <div v-else-if="state.isShowSecond" class="c-f-v c-w-100">
                    <div class="c-f-h c-f-between-center">
                        <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :plain="true" :title="$t('AInputDate.SelectMinute')" @click="
                            state.isShowMinute = true
                        state.isShowSecond = false;
                        "><span>{{
    tempResultInDayjs.format("YYYY-MM-DD HH:mm")
}}</span>
                            <span>:<span class="animate-flash">__</span></span>
                        </a-button>
                        <a-control-group direction="v">
                            <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :square="true" :plain="true" :title="$t('AInputDate.LastMinute')" :halfHeight="true" @click="
                                state.tempValue = tempResultInDayjs
                                    .add(-1, 'minute')
                                    .toDate()
                                ">
                                <span class="fa fa-caret-up"></span>
                            </a-button>
                            <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :square="true" :plain="true" :title="$t('AInputDate.NextMinute')" :halfHeight="true" @click="
                                state.tempValue = tempResultInDayjs
                                    .add(1, 'minute')
                                    .toDate()
                                ">
                                <span class="fa fa-caret-down"></span>
                            </a-button>
                        </a-control-group>
                    </div>
                    <div class="c-f-h c-f-wrap">
                        <a-button v-for="a in 60" :key="a" style="width: 10%" :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :plain="true" class="c-p-0" @click="methods.secondClick(a - 1)">
                            {{ methods.paddingLeft(a - 1, 2) }}
                        </a-button>
                    </div>
                </div>
                <div class="c-f-h c-f-end-center c-b-t" :class="[`c-m-t-${formItemHook.mySize}`]">
                    <div :class="[`c-m-t-${formItemHook.mySize}`]">
                        <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :plain="true" @click="methods.input(new Date())">
                            {{ $t("AInputDate.Now") }}
                        </a-button>
                        <a-button :color="formItemHook.myColor" :size="formItemHook.mySize" :sharp="formItemHook.mySharp" :plain="true" @click="methods.input(state.tempValue)">
                            {{ $t("AInputDate.Done") }}
                        </a-button>
                    </div>
                </div>
            </div>
        </template>
    </a-dropdown>
</template>

<style lang="scss" scoped>
@import "../scss/vars";

@keyframes animate-flash {
    0% {
        opacity: 0;
    }

    50% {
        opacity: 0;
    }

    51% {
        opacity: 1;
    }

    99% {
        opacity: 1;
    }
}

.pop {
    background-color: $defaultBgColor;
    box-sizing: border-box;

    .animate-flash {
        animation: animate-flash 1000ms infinite;
    }
}
</style>

<script setup lang="ts">
import AInputString from './AInputString.vue'
import AButton from './AButton.vue'
import AControlGroup from './AControlGroup.vue'
import ADropdown from './ADropdown.vue'
import utils from "@/common/utils"
import dayjs from 'dayjs'
import { InputPropsType, PopPlacementType, Rule_earliest, Rule_latest } from '@/types'
import { computed, reactive, watch } from 'vue'
import { useFormItem } from '@/hooks/useFormItem'
import { $t } from '@/lang'
import { useInput } from '@/hooks/useInput'

interface PropsType extends InputPropsType<Date | undefined, Rule_earliest | Rule_latest> {
    format?: string
    popPlacement?: PopPlacementType
    clearable?: boolean
    placeholder?: string
    attachButtonShown?: boolean
}
const props = withDefaults(defineProps<PropsType>(), {
    value: undefined,
    color: undefined,
    disabled: undefined,
    size: undefined,
    sharp: undefined,
    rules: () => [],
    isInner: false,
    format: 'YYYY-MM-DD HH:mm:ss',
    popPlacement: 'bottom-start',
    clearable: true,
    placeholder: undefined,
    attachButtonShown: true
})

interface YearTimespanType {
    min: number
    max: number
}
interface StateType {
    popShown: boolean
    isShowYear: boolean
    isShowMonth: boolean
    isShowDate: boolean
    isShowHour: boolean
    isShowMinute: boolean
    isShowSecond: boolean
    currentYearTimespan: YearTimespanType
    tempValue?: Date
}
const state = reactive<StateType>({
    popShown: false,
    isShowYear: false,
    isShowMonth: false,
    isShowDate: false,
    isShowHour: false,
    isShowMinute: false,
    isShowSecond: false,
    currentYearTimespan: {
        min: 0,
        max: 0
    },
    tempValue: undefined
})

useInput(props)
const formItemHook = useFormItem(props)

const displayText = computed(() => {
    return props.value ? dayjs(props.value).format(props.format) : undefined
})
const tempResult = computed(() => {
    return methods.getResultFromDate(state.tempValue)
})
const tempResultInDayjs = computed(() => {
    return dayjs(state.tempValue)
})
const sizePackage = computed(() => {
    return utils.getSizePackageByName(formItemHook.value.mySize)
})
const popWidth = computed(() => {
    return sizePackage.value.size * 10 + sizePackage.value.space * 2
})

watch(() => state.popShown, () => {
    if (state.popShown) {
        methods.showSelector()
    }
})

const emit = defineEmits<{
    (e: 'update:value', value: Date | undefined): void
}>()

const methods = {
    showSelector() {
        state.isShowYear = false
        state.isShowMonth = false
        state.isShowDate = false
        state.isShowHour = false
        state.isShowMinute = false
        state.isShowSecond = false

        if (props.format.indexOf("M") === -1) {
            state.isShowYear = true
        } else if (props.format.indexOf("D") === -1) {
            state.isShowMonth = true
        } else {
            state.isShowDate = true
        }

        let now = new Date()
        let nowYear = now.getFullYear()
        state.currentYearTimespan.min = Math.floor(nowYear / 10) * 10 - 10
        state.currentYearTimespan.max = Math.floor(nowYear / 10) * 10 + 9
        state.tempValue = props.value || now
    },
    input(val: Date | undefined) {
        emit("update:value", val)
        state.popShown = false
    },
    getResultFromDate(dt: Date | undefined) {
        if (!dt) {
            return {
                Y: 0,
                M: 0,
                D: 0,
                H: 0,
                m: 0,
                s: 0
            }
        }
        return {
            Y: dt.getFullYear(),
            M: dt.getMonth(),
            D: dt.getDate(),
            H: dt.getHours(),
            m: dt.getMinutes(),
            s: dt.getSeconds()
        }
    },
    getArrayFromNumberSpan(a: number, b: number) {
        let arr = []
        for (let i = a; i <= b; i++) {
            arr.push(i)
        }
        return arr
    },
    isLeapYear(year: number) {
        if (year % 4 !== 0) {
            return false
        }
        if (year % 100 === 0) {
            return false
        }
        return true
    },
    getDaysCountOfMonth(year: number, month: number) {
        //month是从Date.getMonth()取得，所以是从0开始
        if (month === 1) {
            return methods.isLeapYear(year) ? 29 : 28
        } else if ([0, 2, 4, 6, 7, 9, 11].indexOf(month) > -1) {
            return 31
        } else {
            return 30
        }
    },
    getDayIndexOfFirstDate(year: number, month: number) {
        let dt = new Date(year, month, 1)
        let day = dt.getDay()
        let index = (day || 7) - 1
        return index
    },
    paddingLeft(num: number, totalCount: number) {
        return num.toString().padStart(totalCount, "0")
    },
    yearClick(year: number) {
        state.tempValue = tempResultInDayjs.value.set('year', year).toDate()
        if (props.format.indexOf("M") !== -1) {
            state.isShowYear = false
            state.isShowMonth = true
        }
    },
    monthClick(month: number) {
        state.tempValue = tempResultInDayjs.value.set('month', month - 1).toDate()
        if (props.format.indexOf("D") !== -1) {
            state.isShowMonth = false
            state.isShowDate = true
        }
    },
    dateClick(date: number) {
        state.tempValue = tempResultInDayjs.value.set('date', date).toDate()
        if (props.format.indexOf("H") !== -1) {
            state.isShowDate = false
            state.isShowHour = true
        }
    },
    hourClick(hour: number) {
        state.tempValue = tempResultInDayjs.value.set('hour', hour).toDate()
        if (props.format.indexOf("m") !== -1) {
            state.isShowHour = false
            state.isShowMinute = true
        }
    },
    minuteClick(minute: number) {
        state.tempValue = tempResultInDayjs.value.set('minute', minute).toDate()
        if (props.format.indexOf("s") !== -1) {
            state.isShowMinute = false
            state.isShowSecond = true
        }
    },
    secondClick(second: number) {
        state.tempValue = tempResultInDayjs.value.set('second', second).toDate()
        methods.input(state.tempValue)
    },
}
</script>